package com.nxy.cpfsfe.busi.btmgtsk;


import com.adtec.starring.datapool.EPOper;
import com.adtec.starring.struct.dta.DtaInfo;
import com.adtec.starring.util.SpringUtil;
import com.nxy.cpfsfe.enumtype.RespCd;
import com.nxy.cpfsfe.enumtype.RpcOutputInfoEnum;
import com.nxy.cpfsfe.enumtype.StatEnum;
import com.nxy.cpfsfe.enumtype.TeBatchReqEnum;
import com.nxy.cpfsfe.mybatis.mapper.TbSelfmntnMapper;
import com.nxy.cpfsfe.mybatis.mapper.TeBatchReqMapper;
import com.nxy.cpfsfe.mybatis.pojo.TbSelfmntn;
import com.nxy.cpfsfe.mybatis.pojo.TeBatchReq;
import com.nxy.cpfsfe.util.RpcCommUtil;
import com.nxy.cpfsfe.util.StringUtil;
import com.nxy.cpfsfe.util.XmlUtil;
import com.nxy.cpfsfe.util.zookeeper.DistributedLock;
import com.nxy.cpfsfe.util.zookeeper.ZookeeperLockUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.dao.DataAccessException;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.transaction.TransactionStatus;
import org.springframework.transaction.support.DefaultTransactionDefinition;

import java.sql.Timestamp;
import java.util.Date;
import java.util.List;

public class TbSelfmntnProcBean {
	
	private static TbSelfmntnProcBean instance = new TbSelfmntnProcBean();
	
	private TbSelfmntnProcBean(){
		
	}
	
	public static  TbSelfmntnProcBean getInstance(){
		
		return instance;
	}
	
	
	private	SqlSession sqlSession;
	private final static Logger LOGGER = LoggerFactory.getLogger(TbSelfmntnProcBean.class);
	
	/**
	 * starring定时器调用函数
	 */
	public void timerProc(){
		LOGGER.info("---------定时器执行补发任务开始---------");
		sqlSession =(SqlSession) SpringUtil.getBean("mybatisSqlSession");
		//zookeeper锁定此次补发信息
		DistributedLock distributedLock = null;
		DistributedLock reqDistributedLock = null;

		TbSelfmntn tbSelfmntn = new TbSelfmntn();
		tbSelfmntn.setRepFlg(StatEnum.REPFlG_WAIT.getCode());
		tbSelfmntn.setRepTMs(Integer.parseInt(StatEnum.REP_TMS.getCode()));
		String msgId="";
		try {
			//获取锁
			distributedLock = ZookeeperLockUtil.getInstance().creaZooKeeperLock("tbSelfmntn-update");
			if(distributedLock.tryLock()){
				//查询待补发数据
				List<TbSelfmntn> tbSelfmntnlists = querySelfmntn(sqlSession,tbSelfmntn);
				String rspsCd="";				
				String repFlg=StatEnum.REPFlG_WAIT.getCode();
				if(tbSelfmntnlists != null && tbSelfmntnlists.size() > 0){			
					for(TbSelfmntn tbS :tbSelfmntnlists){
						msgId =tbS.getSeqNb();
						repFlg = StatEnum.REPFlG_WAIT.getCode();
						//当请求业务标识为2批量结算方补发，进行特殊处理
						if(tbS.getBizId()==2){
							reqDistributedLock =  ZookeeperLockUtil.getInstance().creaZooKeeperLock(StringUtil.trimObject(tbS.getRcvSysId())+"TeBatchReq"+tbS.getSeqNb());
							rspsCd = selfmntnFeToGW(tbS);
							TeBatchReqMapper tMapper = sqlSession.getMapper(TeBatchReqMapper.class);
							TeBatchReq teBatchReq = new TeBatchReq();
							teBatchReq.setReqSysId(tbS.getRcvSysId());
							teBatchReq.setBatNo(tbS.getSeqNb());
							if(reqDistributedLock.tryLock()){
//								teBatchReq = tMapper.searchBatchA(teBatchReq);
								teBatchReq.setProcTm(new Date());
								if(RespCd.NCPI0000.equals(rspsCd)){
									//补发成功，修改请求表状态为处理成功
									repFlg=StatEnum.REPFLG_DONE.getCode();
									teBatchReq.setProcSta(TeBatchReqEnum.ProcSta_Success.getCode());
                                    tMapper.updateTeBatchReqStatus(teBatchReq);
                                }else {
									repFlg =StatEnum.REPFlG_WAIT.getCode();
									if(tbS.getRepTMs()>=4){
										//补发失败超过5次，修改请求表状态为处理失败
										teBatchReq.setProcSta(TeBatchReqEnum.ProcSta_Fail.getCode());
										teBatchReq.setProcDesc("补发失败：超过"+(tbS.getRepTMs()+1)+"次");
                                        tMapper.updateTeBatchReqStatus(teBatchReq);
									}
								}
								reqDistributedLock.unlock();
							}
						}else{
							rspsCd = selfmntnFeToGW(tbS);
							if(RespCd.NCPI0000.equals(rspsCd)){
								repFlg=StatEnum.REPFLG_DONE.getCode();

							}else {
								repFlg =StatEnum.REPFlG_WAIT.getCode();
							}
						}
						LOGGER.debug("tebatchtest7");

						tbS.setRepTMs(tbS.getRepTMs()+1);
						tbS.setRepFlg(repFlg);
						tbS.setUpdTm(new Timestamp(new Date().getTime()));
						updateSelfmntnSta(sqlSession,tbS,repFlg);
					}
					
					/*
					deleteSelfmntnSta(sqlSession,tbSelfmntn);
					*/
				}
			}
		
		}catch (DataAccessException e) {

			LOGGER.error("补发任务数据库操作失败报文标识号：msgId=["+msgId+"]",e);
		} catch (Throwable e) {
			LOGGER.error("补发任务数据库操作失败报文标识号：msgId=["+msgId+"]",e);
		}finally {
			//释放锁
			if(distributedLock != null){
				distributedLock.unlock();
			}
			if(reqDistributedLock != null){
				reqDistributedLock.unlock();
			}
		}
		
	}

	
	
	 /**
	  * 
	  * 只对发往网关失败的报文登记补发表
	  * @param bizMsg
	  */

	 public static void regTbSelfmntn(String bizMsg,String sndAppCd,String rcvAppCd) {
		SqlSession sqlSession = (SqlSession) SpringUtil.getBean("mybatisSqlSession");	

		TbSelfmntn tbSelfmntn = new TbSelfmntn();
		try {
			TbSelfmntnMapper tbSelfmntnMapper =  sqlSession.getMapper(TbSelfmntnMapper.class);
			String seqNb = StringUtils.isBlank(XmlUtil.getValByXPath(bizMsg,"/transaction/header/msg/seqNb")) ? XmlUtil.getValByXPath(bizMsg,"/root/MsgHeader/TrxId"): XmlUtil.getValByXPath(bizMsg,"/transaction/header/msg/seqNb");
			String msgCd = StringUtils.isBlank(XmlUtil.getValByXPath(bizMsg,"/transaction/header/msg/msgCd")) ? XmlUtil.getValByXPath(bizMsg,"/root/MsgHeader/MsgTp"): XmlUtil.getValByXPath(bizMsg,"/transaction/header/msg/msgCd");
			LOGGER.debug("补发表tbSelfmntn插入数据：报文标识号seqNb=[{}],报文编号msgCd=[{}]",seqNb,msgCd);
			tbSelfmntn.setSeqNb(seqNb);
			tbSelfmntn.setChlXCd(msgCd);
			tbSelfmntn.setCpfsD(new Date());		
			tbSelfmntn.setSndSysId(sndAppCd);	
			tbSelfmntn.setRcvSysId(rcvAppCd);
			tbSelfmntn.setMsg(bizMsg);
			tbSelfmntn.setBizId(1);
			tbSelfmntn.setRepFlg(StatEnum.REPFlG_WAIT.getCode());
			tbSelfmntn.setCreTm(new Timestamp(new Date().getTime()));

			int tbSelfmntnResult = 0;
			tbSelfmntnResult = tbSelfmntnMapper.insert(tbSelfmntn);
			LOGGER.debug("补发表tbSelfmntn插入数据：[{}]条,报文标识号seqNb=[{}]",tbSelfmntnResult,tbSelfmntn.getSeqNb());
		}catch(DataAccessException e){

			LOGGER.error("补发表tbSelfmntn插入数据失败,报文标识号seqNb=["+tbSelfmntn.getSeqNb()+"],错误栈信息：",e);
		}catch (Throwable e) {
			LOGGER.error("补发表tbSelfmntn插入数据失败,报文标识号seqNb=["+tbSelfmntn.getSeqNb()+"],错误栈信息：",e);
		}
		 

	 }


	
	/**
	 * 发往网关
	 */
	private String selfmntnFeToGW(TbSelfmntn tbSelfmntn) {
		
		 String tpId = DtaInfo.getInstance().getTpId();
		 EPOper.put(tpId, "ReqBean[0].head[0].servEcd", RpcOutputInfoEnum.OutPutSvr_CpfsFwdThrdPrtS.getCode());
		 EPOper.put(tpId, "ReqBean[0].head[0].sndAppCd", tbSelfmntn.getSndSysId());
		 EPOper.put(tpId, "ReqBean[0].head[0].rcvAppCd", tbSelfmntn.getRcvSysId());
    	 //EPOper.put(tpId, "ReqBean[0].head[0].initrSeqno", PubBeanSerial.getInstance().getSeqNoAndIncrea(SysEcodeEnum.CPFS.getCode()));
		 EPOper.put(tpId, "ReqBean[0].head[0].initrSeqno", tbSelfmntn.getSeqNb());
    	 EPOper.put(tpId, "ReqBean[0].head[0].reqServCd", tbSelfmntn.getChlXCd());
    	 //如果请求方为2，报文请求头添加requrl
		if(tbSelfmntn.getBizId()==2){
			 EPOper.put(tpId, "ReqBean[0].head[0].reqUrl", tbSelfmntn.getReqUrl());
		 }
	     EPOper.getCompSDO(tpId, "ReqBody").setValue("BizMsg",tbSelfmntn.getMsg());
	     String rspsCd = RpcCommUtil.getInstance().rpcFeToGW(tpId, RpcOutputInfoEnum.OutputName_Pub_Cpfsgw.getCode(),RpcOutputInfoEnum.OutPutSvr_CpfsFwdThrdPrtS.getCode(),false);
	     rspsCd =  StringUtils.isBlank(rspsCd) ? RespCd.NCPO6047 : rspsCd;
	     return rspsCd;
	}
	

	/**
	 * 查询待补发的业务
	 * @return
	 */
	List<TbSelfmntn> querySelfmntn(SqlSession sqlSession,TbSelfmntn tbSelfmntn) throws DataAccessException {
		
		TbSelfmntnMapper tbSelfmntnMapper =  sqlSession.getMapper(TbSelfmntnMapper.class);
		List<TbSelfmntn> lists = tbSelfmntnMapper.query(tbSelfmntn);
        return lists;
	}
	/**
	 * 更新补发成功的状态
	 * @param
	 */
	public void updateSelfmntnSta(SqlSession sqlSession,TbSelfmntn tbSelfmntn,String repFlg) throws DataAccessException {
		TbSelfmntnMapper tbSelfmntnMapper = sqlSession.getMapper(TbSelfmntnMapper.class);
		tbSelfmntnMapper.update(tbSelfmntn);
		
	}
	
	
	/**
	 * 更删除已补发成功的报文
	 * @param
	 */
	public void deleteSelfmntnSta(SqlSession sqlSession,TbSelfmntn tbSelfmntn) throws DataAccessException {
		TbSelfmntnMapper tbSelfmntnMapper = sqlSession.getMapper(TbSelfmntnMapper.class);
		tbSelfmntn.setRepFlg(StatEnum.REPFLG_DONE.getCode());
		tbSelfmntnMapper.delete(tbSelfmntn);
		
	}



}
